﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

// Reviewed
#pragma once

#include "GcmpModelInterface.h"
#include "IDbObject.h"

namespace gcmp
{ 
    enum class JoinPosition;
    class IMultiJoinDataComponent;
    class IElementJoin;
    class IElement;

    /// \brief 额外的连接次对象数据
    ///
    /// 用于在多构件连接中，表达除了ElementJoin中AttachingId和AttachedId以外参与多构件连接的次对象数据
    struct GCMP_MODEL_INTERFACE_EXPORT SecondaryAttachingJoinData
    {
        /// \brief 构造ExtraAttachingJoinData
        ///
        /// \param attachingId    次对象id
        /// \param attachingPos   次对象连接位置
        SecondaryAttachingJoinData(const ElementId& attachingId, JoinPosition attachingPosition);

        ElementId AttachingElementId;         ///<  次对象id
        JoinPosition   AttachingPosition;     ///<  次对象连接位置
    };

    /// \brief 多构件连接数据
    /// 
    /// 平台已用IElementJoin表达一对一的连接关系，如果需要支持多构件连接，需要在IElementJoin中添加IMultiJoinData用于存储用于实现多构件连接的额外数据
    /// 包括：额外参与连接的次对象的ElementId和连接位置，以及定制化的IMultiJoinDataComponent用于实现一些定制化行为（具体可参考IMultiJoinDataComponent的接口）
    class GCMP_MODEL_INTERFACE_EXPORT IMultiJoinData : public IDbObject
    {
        DEFINE_CAST_DERIVED(gcmp::IMultiJoinData, gcmp::IDbObject);
    public:
        /// \brief 析构函数
        virtual ~IMultiJoinData() {};

        /// \brief 创建多构件连接数据并添加至目标IElementJoin中
        /// 
        /// 已存在ElementJoin表达的连接关系，需要扩展成多构件连接时，需要调用该接口创建多构件连接数据并添加至ElementJoin中
        /// \param IElementJoin               目标IElementJoin
        /// \param opMultiJoinDataComponent   多构件连接行为组件
        /// \return 创建好的多构件连接数据，当目标IElementJoin已存在多构件连接数据时会返回nullptr
        static IMultiJoinData* Create(IElementJoin* pHostJoin, OwnerPtr<IMultiJoinDataComponent> opMultiJoinDataComponent);

        /// \brief 添加额外参与连接的次对象连接数据
        /// \param secondaryAttachingJoindata 次对象连接数据
        /// \return true，添加成功;false，添加失败，如次对象ElementId已存在/ElementId无效/连接位置无效
        virtual bool AddSecondaryAttachingJoinData(SecondaryAttachingJoinData secondaryAttachingJoindata) = 0;

        /// \brief 删除额外参与连接的次对象连接数据
        /// \param id 次对象的ElementId
        /// \return true，删除成功;false，删除失败，如次对象ElementId不存在
        virtual bool DeleteSecondaryAttachingJoinData(const ElementId& id) = 0;

        /// \brief 获取多构件连接数据中额外次连接对象的ElementIds
        /// 
        /// \return 额外次连接对象的ElementIds
        virtual const std::vector<ElementId>& GetSecondaryAttachingElementIds() const = 0;

        /// \brief 获取额外次连接对象的连接位置
        /// 
        /// \param id 目标次连接对象
        /// \return 次连接对象的连接位置，若MultiJoinData中并没有该对象，则返回JoinPosition::Invalid
        virtual JoinPosition GetJoinPostionOfSecondaryAttachingId(const ElementId& id) const = 0;

        /// \brief 获取多构件连接组件
        /// \return 多构件连接组件
        virtual IMultiJoinDataComponent* GetMultiJoinDataComponent() = 0;

        /// \brief 获取多构件连接组件
        /// \return 多构件连接组件
        virtual const IMultiJoinDataComponent* GetMultiJoinDataComponent() const = 0;

        /// \brief 获取所属的ElementJoin
        /// \return 所属ElementJoin
        virtual const IElement* GetOwnerElement() const = 0;

        /// \brief 获取所属的ElementJoin
        /// \return 所属ElementJoin
        virtual IElement* GetOwnerElement() = 0;
    };
}


